From 5435198443737fd0f34f39206e071f2bbbffef10 Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Wed, 16 May 2007 10:42:07 -0600 Subject: [PATCH] [IA64] Fix deadlock of ptc.ga emulation ptc_ga_remote_func() might be invoked by IPI with a schedule_lock that is acquired. (e.g., inside of vcpu_migrate()) It will cause a deadlock. Signed-off-by: Kouya Shimura --- xen/arch/ia64/vmx/vmmu.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/xen/arch/ia64/vmx/vmmu.c b/xen/arch/ia64/vmx/vmmu.c index e0617082b2..d55680505b 100644 --- a/xen/arch/ia64/vmx/vmmu.c +++ b/xen/arch/ia64/vmx/vmmu.c @@ -563,13 +563,16 @@ static void ptc_ga_remote_func (void *varg) struct ptc_ga_args *args = (struct ptc_ga_args *)varg; VCPU *v = args->vcpu; vadr = args->vadr; + int cpu = v->processor; /* Try again if VCPU has migrated. */ - if (v->processor != current->processor) + if (cpu != current->processor) return; - vcpu_schedule_lock_irqsave(v, flags); - if (v->processor != current->processor) - goto bail; + local_irq_save(flags); + if (!spin_trylock(&per_cpu(schedule_data, cpu).schedule_lock)) + goto bail2; + if (v->processor != cpu) + goto bail1; oldrid = VMX(v, vrr[0]); VMX(v, vrr[0]) = args->rid; oldpsbits = VMX(v, psbits[0]); @@ -587,8 +590,10 @@ static void ptc_ga_remote_func (void *varg) ia64_set_pta(mpta); ia64_dv_serialize_data(); args->vcpu = NULL; -bail: - vcpu_schedule_unlock_irqrestore(v, flags); +bail1: + spin_unlock(&per_cpu(schedule_data, cpu).schedule_lock); +bail2: + local_irq_restore(flags); } @@ -598,7 +603,7 @@ IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu, u64 va, u64 ps) struct domain *d = vcpu->domain; struct vcpu *v; struct ptc_ga_args args; - int proc; + int cpu; args.vadr = va; vcpu_get_rr(vcpu, va, &args.rid); @@ -614,13 +619,15 @@ IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu, u64 va, u64 ps) args.vcpu = v; do { - proc = v->processor; - if (proc != vcpu->processor) + cpu = v->processor; + if (cpu != current->processor) { + spin_unlock_wait(&per_cpu(schedule_data, cpu).schedule_lock); /* Flush VHPT on remote processors. */ - smp_call_function_single(proc, &ptc_ga_remote_func, + smp_call_function_single(cpu, &ptc_ga_remote_func, &args, 0, 1); - else + } else { ptc_ga_remote_func(&args); + } } while (args.vcpu != NULL); } return IA64_NO_FAULT; -- 2.30.2